/*******************************************************************************
* Function Name : CAN_init
* Description   : This routine configures the CAN cell and active it.
* Input         : CAN_MasterCtrlReg (options of the CAN controller)
				  - CMCR_ABOM: Automatic bus-off management -> left
				  automatically by HW once 128 x 11 recessive bits,
				  - CMCR_AWUM: Automatic Wake-up mode,
				  - CMCR_NART: No Automatic Retransmission,
				  - CMCR_RFLM: Discard last message when FIFO full,
				  - CMCR_TXFP: Transmit order by FIFO -> Priority by the
				  request order or identifier of the message.
* Output        : .
* Return        : .
*******************************************************************************/  
#include "stm8s_can.h"

volatile unsigned char Can_Page;

void Stm8_can_init(unsigned char CAN_MasterCtrlReg)
{ 
	/* Abort the pending transmit requests */
	CAN_FPSR = CAN_TXMB0_PG;
	CAN_MCSR |= MCSR_ABRQ;    

	CAN_FPSR = CAN_TXMB1_PG;
	CAN_MCSR |= MCSR_ABRQ;
	
	CAN_FPSR = CAN_TXMB2_PG;
	CAN_MCSR |= MCSR_ABRQ;
	
	CAN_MCR |= CMCR_INRQ;				/* Request initialisation */

	/* Wait until acknowledged */
	while ( !(CAN_MSR & CMSR_INAK) )
	{
		;
	}

	/*
		Clear Transmit mailbox empty interrupts (RQCP 0 & 1 & 2) and therefore
		clear TXOK 0 & 1 & 2 bits
	*/
	CAN_TSR |= CTSR_RQCP0 | CTSR_RQCP1 | CTSR_RQCP2;
	
	/* Release the Receive FIFO -> clear FMP bits and FULL bit */
	while(CAN_RFR & CRFR_FMP01)
	{
		CAN_RFR = CRFR_RFOM;
	}
	
	/* Clear the FIFO Overrun (FOVR) bit */
	CAN_RFR |= CRFR_FOVR;
	
	/* Clear Wake-up pending interrupt */
	CAN_MSR = CMSR_WKUI;

	/* ABOM - /NART - TXFP */
	CAN_MCR |= CAN_MasterCtrlReg;

//	CAN_MCR |= CMCR_RFLM;
	/* Filter initialization */
	/* Deactivate all filters */
	CAN_FPSR = CAN_CTRL_PG;	
	CAN_FCR1 = 0x00;
	CAN_FCR2 = 0x00;
	CAN_FCR3 = 0x00;
	
	/* Filter 0 in 1 x 32-bit registers */
	CAN_FCR1 = CAN_FCR1_FILTER0_SCALE_1_32BIT;	
	/* Filter 0 in 1 x 32-bit registers & Filter 1 in 1 x 32-bit registers */
//	CAN_FCR1 = CAN_FCR1_FILTER0_SCALE_1_32BIT | CAN_FCR1_FILTER1_SCALE_1_32BIT;
	/* Filter 2 in 1 x 32-bit registers */
	CAN_FCR2 = CAN_FCR2_FILTER2_SCALE_1_32BIT;	
	/* Filter 2 in 1 x 32-bit registers & Filter 3 in 1 x 32-bit registers */
//	CAN_FCR2 = CAN_FCR2_FILTER2_SCALE_1_32BIT | CAN_FCR2_FILTER3_SCALE_1_32BIT;	
	/* Filter 4 in 1 x 32-bit registers */
	CAN_FCR3 = CAN_FCR3_FILTER4_SCALE_1_32BIT;	
	/* Filter 4 in 1 x 32-bit registers & Filter 5 in 1 x 32-bit registers */
//	CAN_FCR3 = CAN_FCR3_FILTER4_SCALE_1_32BIT | CAN_FCR3_FILTER5_SCALE_1_32BIT;	
	
	CAN_FMR1 = 0x00;	/* Filter 0, 1, 2, 3 Low/High Register in Identifier/Mask mode */
	CAN_FMR2 = 0x00;	/* Filter 4, 5 Low/High Register in Identifier/Mask mode */
	
	/* Filter 0 Low/High Register in Identifier List mode */
//	CAN_FMR1 |= CAN_FMR1_FILTER0_LR_LIST | CAN_FMR1_FILTER0_HR_LIST;	
	/* Filter 0 Low/High Register in Identifier List mode & Filter 1 Low/High Register in Identifier List mode */
//	CAN_FMR1 |= CAN_FMR1_FILTER0_LR_LIST | CAN_FMR1_FILTER0_HR_LIST | CAN_FMR1_FILTER1_LR_LIST | CAN_FMR1_FILTER1_HR_LIST;	
	/* Filter 4 Low/High Register in Identifier List mode */
//	CAN_FMR2 |= CAN_FMR2_FILTER4_LR_LIST | CAN_FMR2_FILTER4_HR_LIST;	
	/* Filter 4 Low/High Register in Identifier List mode & Filter 5 Low/High Register in Identifier List mode */
//	CAN_FMR2 |= CAN_FMR2_FILTER4_LR_LIST | CAN_FMR2_FILTER4_HR_LIST | CAN_FMR2_FILTER5_LR_LIST | CAN_FMR2_FILTER5_HR_LIST;	

	/* Select filter 0:1 Page */
	CAN_FPSR = CAN_FILTER01_PG;	
////////////////////////////////////////////////////////////////////////////////
	/* All ID values are accepted */ 
	CAN_FxR0 = 0x00;	
	CAN_FxR1 = 0x00;
	CAN_FxR2 = 0x00;	
	CAN_FxR3 = 0x00;
	CAN_FxR4 = 0x00;	
	CAN_FxR5 = 0x00;
	CAN_FxR6 = 0x00;	
	CAN_FxR7 = 0x00;	
	
	CAN_FyR0 = 0x00;
	CAN_FyR1 = 0x00;
	CAN_FyR2 = 0x00;
	CAN_FyR3 = 0x00;
	CAN_FyR4 = 0x00;
	CAN_FyR5 = 0x00;
	CAN_FyR6 = 0x00;
	CAN_FyR7 = 0x00;
////////////////////////////////////////////////////////////////////////////////
	
	/* Select filter 2:3 Page */
	CAN_FPSR = CAN_FILTER23_PG;	
////////////////////////////////////////////////////////////////////////////////
	/* All ID values are accepted */ 
	CAN_FxR0 = 0x00;	
	CAN_FxR1 = 0x00;
	CAN_FxR2 = 0x00;	
	CAN_FxR3 = 0x00;
	CAN_FxR4 = 0x00;	
	CAN_FxR5 = 0x00;
	CAN_FxR6 = 0x00;	
	CAN_FxR7 = 0x00;	
	
	CAN_FyR0 = 0x00;
	CAN_FyR1 = 0x00;
	CAN_FyR2 = 0x00;
	CAN_FyR3 = 0x00;
	CAN_FyR4 = 0x00;
	CAN_FyR5 = 0x00;
	CAN_FyR6 = 0x00;
	CAN_FyR7 = 0x00;
////////////////////////////////////////////////////////////////////////////////
	
	/* Select filter 4:5 Page */
	//CAN_FPSR = CAN_FILTER45_PG;	
////////////////////////////////////////////////////////////////////////////////
	/* All ID values are accepted */ 
	CAN_FxR0 = 0xff;	
	CAN_FxR1 = 0xff;
	CAN_FxR2 = 0xff;	
	CAN_FxR3 = 0xff;
	CAN_FxR4 = 0xff;	
	CAN_FxR5 = 0xff;
	CAN_FxR6 = 0xff;	
	CAN_FxR7 = 0xff;	
	
	CAN_FyR0 = 0xff;
	CAN_FyR1 = 0xff;
	CAN_FyR2 = 0xff;
	CAN_FyR3 = 0xff;
	CAN_FyR4 = 0xff;
	CAN_FyR5 = 0xff;
	CAN_FyR6 = 0xff;
	CAN_FyR7 = 0xff;
////////////////////////////////////////////////////////////////////////////////
	
	/* Activate needed filters */
	CAN_FPSR = CAN_CTRL_PG ;	
	CAN_FCR1 |= CAN_FCR1_FILTER0_ACTIVE;	/* Filter 0 active */
	//CAN_FCR1 |= CAN_FCR1_FILTER1_ACTIVE;	/* Filter 1 active */
	//CAN_FCR2 |= CAN_FCR2_FILTER2_ACTIVE;	/* Filter 2 active */
	//CAN_FCR2 |= CAN_FCR2_FILTER3_ACTIVE;	/* Filter 3 active */
	//CAN_FCR3 |= CAN_FCR3_FILTER4_ACTIVE;	/* Filter 4 active */
	//CAN_FCR3 |= CAN_FCR3_FILTER5_ACTIVE;	/* Filter 5 active */

	/* Configure bit timing */
	CAN_FPSR = CAN_CTRL_PG;
	CAN_BTR1 = CAN_CBTR0_REGISTER;		// see can.h for modification of
	CAN_BTR2 = CAN_CBTR1_REGISTER;  	// bit timing parameters.

	CAN_DGR |= CDGR_3TX;	/* 3 Tx mailboxes */ 
  
	CAN_MCR &= ~CMCR_INRQ;				/* Leave the Init mode */
	while ( (CAN_MSR & CMSR_INAK) )	/* Wait until acknowledged */ 
	{
		;
	}
}

/*******************************************************************************
* Function Name : CAN_WakeUp
* Description   : This routine wakes the CAN up.
* Input         : .
* Output        : .
* Return        : .
*******************************************************************************/
void Stm8_can_wakeup(void)
{
	/* Leave Sleep mode */
	CAN_MCR &= ~CMCR_SLEEP;	

	/* Wait until slak bit cleared */
	while(CAN_MSR & CMSR_SLAK)
	{
		;
	}	
}

/*******************************************************************************
* Function Name : CanCanInterruptRestore
* Description   : This service restores all CAN interrupts.
* Input         : .
* Output        : .
* Return        : .
*******************************************************************************/
void Stm8_can_restore (void)
{
	CanSavePg();

	CAN_IER = 	CIER_WKUIE |	/* Wake-up Interrupt */
				CIER_FOVIE | 	/* FIFO overrun Interrupt */
				CIER_FFIE  |	/* FIFO Full Interrupt */
				CIER_FMPIE |	/* FIFO Message Pending Interrupt */
				CIER_TMEIE;		/* Transmit Mailbox Empty Interrupt */

	CAN_FPSR = CAN_CTRL_PG;
	CAN_EIER = CEIER_ERRIE|	/* Error Interrupt */
				CEIER_LECIE|	/* Last Error Code Interrupt */
				CEIER_BOFIE|	/* Bus-Off Interrupt */
				CEIER_EPVIE|	/* Error Passive Interrupt */
				CEIER_EWGIE;	/* Error Warning Interrupt */

	CanRestorePg();
}